#pragma once
#include<iostream>
#include<assert.h>
#include<vector>
namespace lim
{
    template<class t>
    class vector
    {

    public:


            typedef t* iterator;

            typedef const t* const_iterator;

            iterator begin()
            {
                return _start;
            }

            iterator end()
            {
                return _finish;
            }

            const_iterator begin() const
            {
                return _start;
            }
            const_iterator end() const
            {
                return _finish;
            }




            vector()
            :_start (nullptr),
                _finish(nullptr),
                _endofstorage(nullptr)
            {

            }

            vector(int n, const t& value = t())
            {
                _start = new t[n];
                _finish = _start;
                _endofstorage = _start + n;
                for (int i = 0; i < n; i++)
                {
                    *_finish = value;
                    _finish++;
                }
                _endofstorage = _finish;
            }

            template<class inputiterator>
            vector(inputiterator first, inputiterator last)
            {
                iterator it = new t[last - first];
                _start = it;
                _finish = it;
                _endofstorage = it + (last - first);
                while (first != last)
                {
                    *(_finish++) = *(first++);
                }
            }

            vector(const vector<t>& v)
            {

                _start = new t[v.capacity()];
                _finish = _start;
                _endofstorage = _start + v.capacity();
                for (int e : v)
                {
                    *_finish = e;
                    _finish++;
                }
            }

            vector<t>& operator= (vector<t> v)
            {
                swap(v);
                //swap(_finish, v._finish);
                //swap(_endofstorage, v._endofstorage);
                return *this;
            }

            ~vector()
            {
                delete[] _start;
                _start = nullptr;
                _finish = nullptr;
                _endofstorage = nullptr;
            }

            // capacity

            size_t size() const
            {
                return (_finish - _start);
            }

            size_t capacity() const
            {
                return (_endofstorage - _start);
            }

            void reserve(size_t n)
            {
                if (n > capacity())
                {
                    iterator it = new t[n];
                    for (int i = 0; i < size(); i++)
                    {
                        it[i] = _start[i];
                    }
                    size_t s = size();
                    delete[] _start;
                    _start = it;
                    _finish = it + s;
                    _endofstorage = it + n;
                }
            }

            void resize(size_t n, const t& value = t())
            {

                if (n > capacity())
                {
                    reserve(n);
                }
                if (n > size())
                {
                    while(size() != n)
                    {
                        push_back(value);
                    }
                }
                else
                {
                    _finish = _start + n;
                }
            }




            t& operator[](size_t pos)
            {
                return _start[pos];
            }

            const t& operator[](size_t pos)const
            {
                return _start[pos];
            }



            void push_back(const t& x)
            {
                if (_finish == _endofstorage)
                {
                    reserve(capacity() == 0 ? 1: 2*capacity());
                }
                *_finish = x;
                _finish++;
            }
            void pop_back()
            {
                assert(_start != _finish && _finish != nullptr);
                _finish--;
            }

            void swap(vector<t>& v)
            {
                iterator tmp = _start;
                _start = v._start;
                v._start = tmp;

                tmp = _finish;
                _finish = v._finish;
                v._finish = tmp;

                tmp = _endofstorage;
                _endofstorage = v._endofstorage;
                v._endofstorage = tmp;
            }

            iterator insert(iterator pos, const t& x)
            {
                int tmp = pos - begin();

                if (_finish == _endofstorage)
                {
                    reserve(capacity() == 0 ? 1 : 2 * capacity());
                }
                pos = begin() + tmp;
                iterator it = end();
                while (it != pos)
                {
                    *(it + 1) = *it;
                    it--;
                }
                *it = x;
                _finish++;
                return it;
            }

            iterator erase(iterator pos)
            {
                assert(_start != _finish && _finish != nullptr);
                iterator it = pos;
                while (it != end())
                {
                    *it = *(it + 1);
                    it++;
                }
                _finish--;
                return pos;
            }

    private:
        
        iterator _start; 
        iterator _finish; 
        iterator _endofstorage; 

    };

}
